package utils

import (
	"context"
	"fmt"
	"ginchat/models"
	redis "github.com/go-redis/redis/v8"
	"github.com/spf13/viper"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"os"
	"time"
)

// InitConfig 初始化项目配置信息
func InitConfig() {
	viper.SetConfigName("app")    // 读取的配置文件名
	viper.AddConfigPath("config") // 读取的配置目录
	err := viper.ReadInConfig()
	if err != nil {
		fmt.Println("读取viper错误", err)
	}
}

var MySqlDB *gorm.DB
var MysqlErr error

// InitMysqlDb 使用yml配置文件调用
func InitMysqlDb() {
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢SQL阈值
			Colorful:                  true,        // 彩色
			IgnoreRecordNotFoundError: false,
			ParameterizedQueries:      false,
			LogLevel:                  logger.Info, // 级别
		})
	dns := viper.GetString("mysql.dns")
	MySqlDB, MysqlErr = gorm.Open(mysql.Open(dns), &gorm.Config{
		// gorm日志模式：silent
		//Logger: logger.Default.LogMode(logger.Silent), 不显示SQL
		//Logger: logger.Default.LogMode(logger.Info), // 显示所有SQL
		Logger: newLogger,
		// 外键约束
		DisableForeignKeyConstraintWhenMigrating: true,
		// 禁用默认事务（提高运行速度）
		SkipDefaultTransaction: true,
		NamingStrategy: schema.NamingStrategy{
			// 使用单数表名，启用该选项，此时，`User` 的表名应该是 `user`
			SingularTable: true,
		},
	})
	if MysqlErr != nil {
		fmt.Println("初始化MySQL失败", MysqlErr)
	}

	// 迁移 schema // 设置MySQL数据格式为utf8才能使用中文
	err := MySqlDB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").
		AutoMigrate(&models.UserBasic{}, &models.Message{}, models.Contract{}, models.GroupBasic{})
	if err != nil {
		return
	}

	MySqlDB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8") // 设置MySQL数据格式为utf8
}

var RedisDB *redis.Client

// InitRedis 初始化redis
func InitRedis() {
	RedisDB = redis.NewClient(&redis.Options{
		Addr: viper.GetString("redis.addr"),
		DB:   viper.GetInt("redis.DB"),
	})
	fmt.Println(RedisDB)

	pong, err := RedisDB.Ping(RedisDB.Context()).Result()
	if err != nil {
		fmt.Println("redis连接失败", err)
	}
	fmt.Println(pong)
}

const (
	PublishKey = "websocket"
)

// Publish 发起Publish 发消息到redis
func Publish(c context.Context, channel string, msg string) error {
	var err error
	fmt.Println("现在准备发布消息")
	err = RedisDB.Publish(c, channel, msg).Err()
	return err
}

// Subscribe Subscribe订阅redis消息
func Subscribe(c context.Context, channel string) (string, error) {
	sub := RedisDB.PSubscribe(c, channel)
	fmt.Println("订阅消息------==")
	fmt.Println("Subscribe。。。", sub)
	msg, err := sub.ReceiveMessage(c)
	return msg.Payload, err

}
